#include "asm_utils.h"
#include "interrupt.h"
#include "stdio.h"
#include "program.h"
#include "thread.h"
#include "sync.h"
#include "memory.h"

// 屏幕IO处理器
STDIO stdio;
// 中断管理器
InterruptManager interruptManager;
// 程序管理器
ProgramManager programManager;
// 内存管理器
MemoryManager memoryManager;

void first_thread(void *arg)
{
    // 第1个线程不可以返回

    char *p1 = (char *)memoryManager.allocatePages(AddressPoolType::KERNEL, 1000);
    printf("pid p1 allocate 1000  pages. The start address: %x\n",p1);
    char *p2 = (char *)memoryManager.allocatePages(AddressPoolType::KERNEL, 100);
    printf("pid p2 allocate 100   pages. The start address: %x\n",p2);
    char *p3 = (char *)memoryManager.allocatePages(AddressPoolType::KERNEL, 10000);
    printf("pid p3 allocate 10000 pages. The start address: %x\n",p3);
    char *p4 = (char *)memoryManager.allocatePages(AddressPoolType::KERNEL, 100);
    printf("pid p4 allocate 100   pages. The start address: %x\n",p4);
	
    memoryManager.releasePages(AddressPoolType::KERNEL, (int)p1, 1000);
    printf("pid p1 has released.\n");
    
    memoryManager.releasePages(AddressPoolType::KERNEL, (int)p3, 10000);
    printf("pid p3 has released.\n");
   
    char *p6 = (char *)memoryManager.allocatePages(AddressPoolType::KERNEL, 350);
    printf("pid p6 allocate 350   pages. The start address: %x\n",p6);
 
    char *p7 = (char *)memoryManager.allocatePages(AddressPoolType::KERNEL, 350);
    printf("pid p7 allocate 350   pages. The start address: %x\n",p7);
    
    memoryManager.releasePages(AddressPoolType::KERNEL, (int)p6, 350);
    printf("pid p6 has released.\n");
    
    char *p8 = (char *)memoryManager.allocatePages(AddressPoolType::KERNEL, 200);
    printf("pid p8 allocate 200   pages. The start address: %x\n",p8);
   
    asm_halt();
}

extern "C" void setup_kernel()
{

    // 中断管理器
    interruptManager.initialize();
    interruptManager.enableTimeInterrupt();
    interruptManager.setTimeInterrupt((void *)asm_time_interrupt_handler);

    // 输出管理器
    stdio.initialize();

    // 进程/线程管理器
    programManager.initialize();

    // 内存管理器
    memoryManager.openPageMechanism();
    memoryManager.initialize();

    // 创建第一个线程
    int pid = programManager.executeThread(first_thread, nullptr, "first thread", 1);
    if (pid == -1)
    {
        printf("can not execute thread\n");
        asm_halt();
    }

    ListItem *item = programManager.readyPrograms.front();
    PCB *firstThread = ListItem2PCB(item, tagInGeneralList);
    firstThread->status = RUNNING;
    programManager.readyPrograms.pop_front();
    programManager.running = firstThread;
    asm_switch_thread(0, firstThread);

    asm_halt();
}
